package com.lzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lzy.context.LocalUser;
import com.lzy.dao.SysRoleDao;
import com.lzy.entity.*;
import com.lzy.enums.ExceptionEnums;
import com.lzy.exception.AlreadyExistException;
import com.lzy.exception.ServiceException;
import com.lzy.service.*;
import com.lzy.utils.UserUtil;
import com.lzy.vo.AuthorDeptVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class SysRoleService extends ServiceImpl<SysRoleDao, SysRoleEntity> implements ISysRoleService {

    @Autowired
    private SysRoleDao mapper;

    @Autowired
    private ISysRoleDeptService iSysRoleDeptService;

    @Autowired
    private ISysUserRoleService iSysUserRoleService;

    @Autowired
    private ISysRoleMenuService iSysRoleMenuService;

    @Autowired
    private ISysMenuService iSysMenuService;

    @Override
    public List<SysRoleEntity> selectUserRoles(Long userId) {
        return mapper.selectRoleByUserIdRoleName(userId);
    }

    @Override
    public SysRoleEntity selectRoleInfoByRoleId(Long roleId) {

        return mapper.selectById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveNewRoleInfo(SysRoleEntity sysRole) {

        int count = mapper.checkWhetherExists(sysRole.getRoleKey(), sysRole.getRoleName());
        if (count > 0) {
            throw new AlreadyExistException(ExceptionEnums.ROLE_ALREADY_EXISTS.getCode(), ExceptionEnums.ROLE_ALREADY_EXISTS.getMessage());
        }
        sysRole.setCreateBy(LocalUser.me().getUserName());
        sysRole.setCreateTime(new Date());
        mapper.insert(sysRole);
        insertRoleMenuRelation(sysRole);
    }

    @Override
    public void insertRoleMenuRelation(SysRoleEntity sysRole) {
        List<SysRoleMenuEntity> result = new ArrayList<>();
        for (Long menuId : sysRole.getMenuIds()) {
            SysRoleMenuEntity sysRoleMenuEntity = new SysRoleMenuEntity();
            sysRoleMenuEntity.setRoleId(sysRole.getRoleId());
            sysRoleMenuEntity.setMenuId(menuId);
            result.add(sysRoleMenuEntity);
        }

        if (result.size() > 0) {
            iSysRoleMenuService.batchInsertInfo(result);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleInfo(SysRoleEntity sysRole) {
        int count = mapper.checkWhetherExists(sysRole.getRoleKey(), sysRole.getRoleName());
        if (count > 0) {
            throw new AlreadyExistException(ExceptionEnums.ROLE_ALREADY_EXISTS.getCode(), ExceptionEnums.ROLE_ALREADY_EXISTS.getMessage());
        }
        sysRole.setUpdateBy(LocalUser.me().getUserName());
        sysRole.setUpdateTime(new Date());
        mapper.updateById(sysRole);
        // 删除角色菜单关联表
        iSysRoleMenuService.remove(Wrappers.<SysRoleMenuEntity>lambdaUpdate().eq(SysRoleMenuEntity::getRoleId, sysRole.getRoleId()));
        insertRoleMenuRelation(sysRole);
    }

    @Override
    public Set<String> selectUserPermission(Set<SysRoleEntity> roles) {
        boolean admin = UserUtil.isAdmin(roles.stream().map(item -> item.getRoleKey()).collect(Collectors.toSet()));
        Set<String> menuPermission = null;
        if (!admin) {
            Set<Long> menuIds = iSysRoleMenuService
                    .list(new QueryWrapper<SysRoleMenuEntity>().in("role_id", roles.stream().map(item -> item.getRoleId()).collect(Collectors.toSet())))
                    .stream()
                    .map(item -> item.getMenuId())
                    .collect(Collectors.toSet());
            menuPermission = iSysMenuService
                    .list(new QueryWrapper<SysMenuEntity>()
                            .in("menu_id", menuIds))
                    .stream()
                    .map(item -> item.getPerms())
                    .collect(Collectors.toSet());
        } else {
            menuPermission = iSysMenuService
                    .list(null)
                    .stream()
                    .map(item -> item.getPerms())
                    .collect(Collectors.toSet());
        }


        return menuPermission;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void authorDept(AuthorDeptVo authorDeptVo) {
        // 删除角色与部门关联
        iSysRoleDeptService.deleteRoleDeptByRoleId(authorDeptVo.getRoleId());
        // 新增角色和部门信息（数据权限）
        insertRoleDept(authorDeptVo);
    }

    @Override
    public void insertRoleDept(AuthorDeptVo authorDeptVo) {
        List<SysRoleDeptEntity> result = new ArrayList<>();
        for (Long deptId : authorDeptVo.getDeptIds()) {
            SysRoleDeptEntity sysRoleDeptEntity = new SysRoleDeptEntity();
            sysRoleDeptEntity.setDeptId(deptId);
            sysRoleDeptEntity.setRoleId(authorDeptVo.getRoleId());
            result.add(sysRoleDeptEntity);
        }

        iSysRoleDeptService.saveBatch(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(List<Long> roleIds) {
        for (Long roleId : roleIds) {
            SysRoleEntity role = selectRoleInfoByRoleId(roleId);
            if (checkAlreadyUsing(roleId)) {
                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }
    }

    @Override
    public boolean checkAlreadyUsing(Long roleId) {
        int size = iSysUserRoleService.list(Wrappers.<SysUserRoleEntity>lambdaQuery().eq(SysUserRoleEntity::getRoleId, roleId)).size();

        return true;
    }

    @Override
    public List<SysRoleEntity> selectAllRolesByConditional(SysRoleEntity sysRoleEntity) {
        return null;
    }
}